package com.example.demo.controller;

import com.example.demo.dto.TorrentDetailResponse;
import com.example.demo.dto.TorrentResponse;
import com.example.demo.dto.TorrentSearchResult;
import com.example.demo.model.Torrent;
import com.example.demo.model.TorrentUsage;
import com.example.demo.model.es.TorrentES;
import com.example.demo.service.RecommendationService;
import com.example.demo.service.TorrentSearchService;
import com.example.demo.service.TorrentService;
import com.example.demo.mapper.TorrentUsageMapper;
import com.example.demo.utils.TorrentUtil;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.data.domain.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.net.URI;
import java.text.DecimalFormat;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/torrents")
public class TorrentController {
    private final TorrentService torrentService;

    @Autowired
    private TorrentSearchService torrentSearchService;

    @Autowired
    public TorrentController(TorrentService torrentService) {
        this.torrentService = torrentService;
    }

    @Autowired
    private RecommendationService recommendationService;

    @Autowired
    private TorrentUsageMapper torrentUsageMapper;

    @PostMapping("/upload")
//    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> uploadTorrent(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "description", required = false) String description,
            @RequestParam(value = "type", required = false) String type,
            @RequestParam(value = "firstType", required = false) String firstType,
            @RequestParam(value = "secondType", required = false) String secondType,
            @RequestParam(value = "thirdType", required = false) String thirdType,
            @RequestParam(value = "fourthType", required = false) String fourthType,
            @RequestParam(value = "cost", defaultValue = "50") String cost,
            @RequestParam(value = "coverImage", required = false) MultipartFile coverImage,
            @RequestParam(value = "tags", required = false) String tags) throws IOException {
        try {
            // 验证文件
            if (file == null || file.isEmpty()) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
            }

            double torrentDefaultValue = torrentService.getTorrentDefaultCost();

            // 保存种子文件
            File torrentFile = TorrentUtil.multipartFileToFile(file);
            //初始化种子
            Torrent torrent = new Torrent();
            torrent.setName(name);
            torrent.setDescription(description);
            torrent.setType(type);
            torrent.setFirstType(firstType);
            torrent.setSecondType(secondType);
            torrent.setThirdType(thirdType);
            torrent.setFourthType(fourthType);
            torrent.setCost(String.valueOf(torrentDefaultValue));
            torrent.setTags(tags);

            // 保存封面图片
            String coverImageUrl = null;
            if (coverImage != null && !coverImage.isEmpty()) {
                coverImageUrl = torrentService.saveCoverImage(coverImage); // 保存图片并返回URL
            }

            torrent.setCoverImage(coverImageUrl); // 存储图片的URL

            // 上传种子
            Torrent torrent_with_File = torrentService.uploadTorrent(torrentFile,file,torrent);
            torrentFile.delete(); // 手动删除临时文件
            return ResponseEntity.ok(torrent_with_File);
        } catch (IOException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @GetMapping("/{torrentId}/download")
//    @PreAuthorize("hasRole('USER')")
    @Transactional
    public ResponseEntity<?> downloadTorrent(
            @PathVariable String torrentId) throws IOException {

        // 获取种子信息
        String infoHash = torrentService.getInfoByTorrentId(torrentId);
        Torrent torrent = torrentService.getTorrentByHash(infoHash);
        if (torrent == null || torrent.getFileName() == null) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "种子不存在或文件名缺失");
        }

        // 执行下载逻辑
        torrentService.downloadTorrent(torrent.getId());

        // 返回种子文件
        return ResponseEntity.ok()
                .header("Content-Disposition", "attachment; filename=\"" + torrent.getFileName() + "\"")
                .body(torrentService.getTorrentFile(torrent));
    }

    @GetMapping("/list")
//    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> listTorrents(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            // 获取用户的角色信息
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            // 打印角色信息
            authorities.forEach(authority -> System.out.println("Role: " + authority.getAuthority()));
        }
        return ResponseEntity.ok(torrentService.getAllTorrents());
    }
//    public List<Torrent> listTorrents() {
//        return torrentService.getAllTorrents();
//    }

    @GetMapping("/view/{torrentId}")
//    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> viewTorrent(@PathVariable String torrentId){
        Torrent torrent = torrentService.viewTorrentById(Long.parseLong(torrentId));
        if (torrent == null) {
            return ResponseEntity.notFound().build();
        }

        TorrentDetailResponse response = torrentService.getTorrentDetail(Long.parseLong(torrentId));
        return ResponseEntity.ok(response);
    }

    private String formatFileSize(long size) {
        if (size <= 0) return "0";
        final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" };
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    private TorrentSearchResult convertToSearchResult(TorrentES torrentES) {
        TorrentSearchResult result = new TorrentSearchResult();
        result.setTorrentES(torrentES);


        // 获取附加数据（例如下载次数）
        TorrentUsage usage = torrentUsageMapper.findByTorrentId(torrentES.getId());
        result.setDownloads(usage != null ? usage.getDownloadCount() : 0);
        Torrent torrent = torrentService.getTorrentById(torrentES.getId());
        result.setCost(torrent.getCost());
        result.setFileSize(torrent.getFileSize());
        result.setType(torrent.getType());
        result.setFileName(torrent.getFileName());
        result.setId(torrent.getId());
        result.setFormattedSize(formatFileSize(torrent.getFileSize()));

        return result;
    }
    @GetMapping("/search")
    public ResponseEntity<Page<TorrentSearchResult>> search(
            @RequestParam String name,
            @RequestParam String type,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "createTime,desc") String sort) {


        if ("ai".equals(type)) {
            // 如果 type 是 "ai"，重定向到 /search/description 接口
            // 构建重定向的 URL
            UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/api/torrents/search/description")
                    .queryParam("description", name)
                    .queryParam("page", page)
                    .queryParam("size", size)
                    .queryParam("sort", sort);

            URI redirectUri = builder.build().toUri();
            return ResponseEntity.status(HttpStatus.TEMPORARY_REDIRECT)
                    .location(redirectUri)
                    .build();
        }
            else{
            //        Pageable pageable = PageRequest.of(page, size, Sort.by(sort.split(",")));
            Sort sort1 = Sort.by(Sort.Order.desc("createTime")); // 确保字段名正确
            Pageable pageable = PageRequest.of(page, size, sort1);
            Page<TorrentES> results = torrentSearchService.search(name, pageable);
            // 将 TorrentES 转换为 TorrentSearchResult
            List<TorrentSearchResult> content = results.getContent().stream()
                    .map(this::convertToSearchResult)
                    .collect(Collectors.toList());

            // 创建新的 Page 对象
            Page<TorrentSearchResult> searchResults = new PageImpl<>(content, pageable, results.getTotalElements());

            return ResponseEntity.ok(searchResults);
        }

    }

    @GetMapping("/search/advanced")
//    @PreAuthorize("hasRole('VIP')")
    public ResponseEntity<Page<TorrentES>> advancedSearch(
            @RequestParam(required = false) String title,
            @RequestParam(required = false) String category,
            @RequestParam(required = false) List<String> keywords,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "seeders,desc") String sort) {

        Pageable pageable = PageRequest.of(page, size, Sort.by(sort.split(",")));
        Page<TorrentES> results = torrentSearchService.advancedSearch(title, category, keywords, pageable);
        return ResponseEntity.ok(results);
    }

    @GetMapping("/search/description")
//    @PreAuthorize("hasRole('VIP')")
    public ResponseEntity<Page<TorrentSearchResult>> searchByDescription(
            @RequestParam String description,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "createTime,desc") String sort) throws IOException, InterruptedException {

        Sort sortObj = Sort.by(Sort.Order.desc("createTime"));
        Pageable pageable = PageRequest.of(page, size, sortObj);

        // 调用服务
        Page<TorrentES> results = torrentSearchService.searchByDescription(description, pageable);
        List<TorrentSearchResult> content = results.getContent().stream()
                .map(this::convertToSearchResult)
                .collect(Collectors.toList());

        // 创建新的 Page 对象
        Page<TorrentSearchResult> searchResults = new PageImpl<>(content, pageable, results.getTotalElements());

        return ResponseEntity.ok(searchResults);
    }

    // 热门下载
    @GetMapping("/hot")
    public ResponseEntity<List<TorrentResponse>> getHotTorrents() {
        return ResponseEntity.ok(recommendationService.getHotTorrents());
    }

    // 最新上传
    @GetMapping("/latest")
    public ResponseEntity<List<TorrentResponse>> getLatestTorrents() {
        return ResponseEntity.ok(recommendationService.getLatestTorrents());
    }

    // 协同推荐-用户CF
    @GetMapping("/recommend/collaborative")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<List<TorrentResponse>> recommendByCollaborative(@RequestParam Long userId) {
        return ResponseEntity.ok(recommendationService.recommendByUserCF(userId));
    }

    // 协同推荐-资源CF
    @GetMapping("/{infoHash}/collaborative")
    public ResponseEntity<List<TorrentResponse>> getCollaborativeRelated(@PathVariable String infoHash) {
        return ResponseEntity.ok(recommendationService.recommendRelatedTorrentsCF(infoHash));
    }

}